package icu.cqcai.xinsi.controller;

import com.fasterxml.jackson.databind.ObjectMapper;
import icu.cqcai.xinsi.domain.InterviewAnalysis;
import icu.cqcai.xinsi.domain.InterviewAnswer;
import icu.cqcai.xinsi.domain.InterviewSession;
import icu.cqcai.xinsi.domain.User;
import icu.cqcai.xinsi.mapper.InterviewAnswerMapper;
import icu.cqcai.xinsi.mapper.InterviewSessionMapper;
import icu.cqcai.xinsi.mapper.UserMapper;
import icu.cqcai.xinsi.service.InterviewEvaluationService;
import icu.cqcai.xinsi.util.JwtUtil;
import icu.cqcai.xinsi.service.PdfReportService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;
import org.springframework.http.ContentDisposition;
import java.time.format.DateTimeFormatter;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.ArrayList;

/**
 * 面试控制器 - AI智能面试系统核心控制器
 * 
 * 主要功能：
 * 1. AI面试题目智能生成 - 基于岗位、经验、技能生成个性化题目
 * 2. 面试答案管理 - 支持答案保存、修改、提交等完整流程
 * 3. 面试会话管理 - 创建会话、跟踪进度、管理状态
 * 4. 面试结果分析 - AI评估答案质量并生成分析报告
 * 5. 面试记录查询 - 历史面试记录的查询和管理
 * 
 * 技术特点：
 * - 集成扣子(Coze) AI工作流，实现智能题目生成
 * - 支持多种题目解析算法，确保题目提取准确性
 * - 完整的用户认证和权限控制
 * - 数据持久化存储，支持断点续答
 * - 智能文本解析，支持多种格式的AI回复
 * 
 * 业务流程：
 * 用户输入岗位信息 → AI生成题目 → 用户逐题回答 → AI评估分析 → 生成报告
 * 
 * @author xinsi团队
 * @version 1.0
 * @since 2024
 */
@Controller
@RequestMapping("/interview")
public class InterviewController {

    /**
     * 日志记录器 - 用于记录面试控制器的操作日志
     */
    private static final Logger logger = LoggerFactory.getLogger(InterviewController.class);

    /**
     * REST模板 - 用于调用外部API（扣子工作流）
     */
    @Autowired
    private RestTemplate restTemplate;
    
    /**
     * 面试答案数据访问层 - 处理答案的增删改查操作
     */
    @Autowired
    private InterviewAnswerMapper interviewAnswerMapper;
    
    /**
     * 面试会话数据访问层 - 处理面试会话的数据库操作
     */
    @Autowired
    private InterviewSessionMapper interviewSessionMapper;
    
    /**
     * 用户数据访问层 - 处理用户相关数据查询
     */
    @Autowired
    private UserMapper userMapper;
    
    /**
     * JWT工具类 - 用于Token解析和用户身份验证
     */
    @Autowired
    private JwtUtil jwtUtil;
    
    /**
     * 面试评估服务 - 处理AI评估和分析报告生成
     */
    @Autowired
    private InterviewEvaluationService interviewEvaluationService;

    @Autowired
    private PdfReportService pdfReportService;

    // ==================== 扣子工作流配置常量 ====================
    /**
     * 扣子工作流API接口地址 - 用于调用AI生成面试题目
     */
    private static final String COZE_WORKFLOW_API_URL = "https://api.coze.cn/v1/workflow/run";
    
    /**
     * 扣子API访问令牌 - 用于API认证授权
     */
    private static final String ACCESS_TOKEN = "pat_SwmNZRUPekSdjR31xF4jXMlc6tAV4k50Hiy6dZIsJLVmgK7VUk2gfsKWRTEbDO49";
    
    /**
     * 扣子工作空间ID - 指定工作流所属的空间
     */
    private static final String SPACE_ID = "7514500344975212563";
    
    /**
     * 扣子工作流ID - 面试题目生成专用工作流的唯一标识
     */
    private static final String WORKFLOW_ID = "7516847630732378127";

    /**
     * 面试题页面入口
     * 
     * 功能说明：
     * - 返回面试题目生成和答题的主页面
     * - 支持用户输入岗位信息和技能要求
     * 
     * @return 面试题页面模板名称
     */
    @GetMapping
    public String interviewPage() {
        return "mianshiwenti";
    }

    /**
     * 生成AI面试题目
     * 
     * 核心功能：
     * 1. 接收用户输入的岗位、经验、技能信息
     * 2. 调用扣子AI工作流生成个性化面试题目
     * 3. 解析AI回复并结构化题目数据
     * 4. 创建面试会话并保存题目到数据库
     * 5. 返回格式化的题目列表给前端
     * 
     * 智能特性：
     * - 基于岗位特点生成针对性题目
     * - 根据工作经验调整题目难度
     * - 结合技能要求生成相关题目
     * 
     * 数据处理：
     * - 支持多种AI回复格式的智能解析
     * - 自动生成会话ID进行状态跟踪
     * - 为每个题目创建空答案记录
     * 
     * @param request 包含岗位信息的请求体
     *                - post: 岗位名称（必填）
     *                - workExperience: 工作经验（必填）
     *                - skill: 技能描述（必填）
     * @param token JWT认证令牌，用于用户身份验证
     * @return ResponseEntity 包含生成的题目列表和会话信息
     */
    @PostMapping("/generate")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> generateQuestions(@RequestBody Map<String, String> request,
                                                               @RequestHeader(value = "Authorization", required = false) String token) {
        logger.info("=== 开始生成面试题目 ===");
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 提取请求参数
            String post = request.get("post");
            String workExperience = request.get("workExperience");
            String skill = request.get("skill");
            
            logger.info("接收到题目生成请求 - 岗位: {}, 工作经验: {}, 技能要求: {}", 
                       post, workExperience, skill);
            
            // ========== 参数验证 ==========
            // 验证岗位名称
            if (post == null || post.trim().isEmpty()) {
                logger.warn("参数验证失败: 岗位名称为空");
                response.put("success", false);
                response.put("message", "岗位名称不能为空");
                return ResponseEntity.badRequest().body(response);
            }
            
            // 验证工作经验
            if (workExperience == null || workExperience.trim().isEmpty()) {
                logger.warn("参数验证失败: 工作经验为空");
                response.put("success", false);
                response.put("message", "工作经验不能为空");
                return ResponseEntity.badRequest().body(response);
            }
            
            // 验证技能描述
            if (skill == null || skill.trim().isEmpty()) {
                logger.warn("参数验证失败: 技能描述为空");
                response.put("success", false);
                response.put("message", "技能描述不能为空");
                return ResponseEntity.badRequest().body(response);
            }
            
            // ========== 调用AI工作流生成题目 ==========
            logger.info("开始调用扣子AI工作流生成面试题目");
            String questionsText = callCozeWorkflow(post.trim(), workExperience.trim(), skill.trim());
            
            if (questionsText != null && !questionsText.isEmpty()) {
                logger.info("AI工作流调用成功，返回内容长度: {}", questionsText.length());
                
                // ========== 解析AI生成的题目文本 ==========
                logger.info("开始解析AI生成的题目文本");
                List<Map<String, Object>> questions = parseQuestions(questionsText);
                logger.info("题目解析完成，共解析出 {} 道题目", questions.size());
                
                // ========== 生成唯一会话ID ==========
                String sessionId = "interview_" + System.currentTimeMillis() + "_" + Long.toHexString(Double.doubleToLongBits(Math.random()));
                logger.info("生成面试会话ID: {}", sessionId);
                
                // ========== 保存面试会话和题目数据 ==========
                User user = getCurrentUser(token);
                if (user != null) {
                    try {
                        logger.info("开始保存面试会话数据，用户ID: {}", user.getId());
                        
                        // 创建面试会话记录
                        InterviewSession session = new InterviewSession(user.getId(), sessionId, post.trim(), workExperience.trim(), skill.trim());
                        session.setTotalQuestions(questions.size());
                        interviewSessionMapper.insertSession(session);
                        logger.info("创建面试会话成功: {}, 题目数量: {}", sessionId, questions.size());
                        
                        // 为每个题目创建空的答案记录（状态为未回答）
                        // 这样可以支持断点续答功能
                        for (Map<String, Object> question : questions) {
                            InterviewAnswer answer = new InterviewAnswer();
                            answer.setUserId(user.getId());
                            answer.setSessionId(sessionId);
                            answer.setQuestionId((Integer) question.get("id"));
                            answer.setQuestionTitle((String) question.get("title"));
                            answer.setQuestionContent((String) question.get("content"));
                            answer.setQuestionCategory((String) question.get("category"));
                            answer.setAnswerContent(""); // 初始为空答案
                            answer.setStatus(0); // 0-未回答，1-已回答，2-已提交
                            answer.setCreateTime(LocalDateTime.now());
                            answer.setUpdateTime(LocalDateTime.now());
                            
                            interviewAnswerMapper.insertAnswer(answer);
                        }
                        logger.info("为会话 {} 创建了 {} 个题目记录", sessionId, questions.size());
                        
                    } catch (Exception e) {
                        // 数据库操作失败不影响题目返回，保证用户体验
                        logger.error("保存面试会话失败: ", e);
                        // 继续返回题目，不因为保存失败而影响用户体验
                    }
                } else {
                    logger.warn("用户未登录，跳过会话数据保存");
                }
                
                // ========== 构建成功响应 ==========
                response.put("success", true);
                response.put("message", "面试题目生成成功");
                response.put("questions", questions);
                response.put("sessionId", sessionId); // 返回会话ID给前端
                response.put("rawOutput", questionsText); // 保留原始输出用于调试
                
                logger.info("面试题目生成成功，会话ID: {}, 题目数量: {}", sessionId, questions.size());
                return ResponseEntity.ok(response);
            } else {
                // AI工作流调用失败
                logger.error("AI工作流调用失败，未返回有效内容");
                response.put("success", false);
                response.put("message", "面试题目生成失败，请稍后重试");
                return ResponseEntity.internalServerError().body(response);
            }
            
        } catch (Exception e) {
            // 异常处理：记录详细错误信息
            logger.error("生成面试题目失败: ", e);
            
            response.put("success", false);
            response.put("message", "服务器内部错误: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        } finally {
            logger.info("=== 面试题目生成处理完成 ===");
        }
    }

    /**
     * 调用扣子工作流生成面试题目
     * 
     * 技术实现：
     * 1. 构建标准的扣子API请求体
     * 2. 设置必要的认证头信息
     * 3. 发送HTTP POST请求到扣子API
     * 4. 解析响应并提取题目内容
     * 
     * 错误处理：
     * - 网络请求异常处理
     * - API认证失败处理
     * - 响应格式解析异常处理
     * 
     * @param post 岗位名称
     * @param workExperience 工作经验描述
     * @param skill 技能要求描述
     * @return String AI生成的题目文本，失败时返回null
     */
    private String callCozeWorkflow(String post, String workExperience, String skill) {
        logger.info("开始调用扣子工作流 - 岗位: {}, 经验: {}, 技能: {}", post, workExperience, skill);
        
        try {
            // ========== 构建API请求体 ==========
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("workflow_id", WORKFLOW_ID);
            requestBody.put("parameters", Map.of(
                "post", post,
                "WorkExperience", workExperience,
                "skill", skill
            ));

            logger.debug("扣子工作流请求体: {}", requestBody);

            // ========== 设置HTTP请求头 ==========
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            headers.set("Authorization", "Bearer " + ACCESS_TOKEN);
            headers.set("Space-Id", SPACE_ID);

            HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);

            // ========== 发送HTTP POST请求 ==========
            ResponseEntity<Map> response = restTemplate.postForEntity(COZE_WORKFLOW_API_URL, request, Map.class);
            
            logger.info("扣子工作流响应状态: {}", response.getStatusCode());
            logger.debug("扣子工作流响应内容: {}", response.getBody());
            
            // ========== 详细的响应分析日志 ==========
            if (response.getBody() != null) {
                logger.debug("响应体类型: {}", response.getBody().getClass().getName());
            }
            
            // ========== 解析API响应数据 ==========
            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                Map<String, Object> responseBody = response.getBody();
                
                // 检查响应结构：先检查data字段，再检查output字段
                if (responseBody.containsKey("data")) {
                    Object dataField = responseBody.get("data");
                    
                    // 如果data字段是字符串类型（JSON字符串），需要二次解析
                    if (dataField instanceof String) {
                        try {
                            // 解析嵌套的JSON字符串
                            ObjectMapper objectMapper = new ObjectMapper();
                            Map<String, Object> dataObject = objectMapper.readValue((String) dataField, Map.class);
                            if (dataObject != null && dataObject.containsKey("output")) {
                                String output = (String) dataObject.get("output");
                                logger.info("成功解析到output内容，长度: {}", output.length());
                                logger.debug("Output前100字符: {}", output.substring(0, Math.min(100, output.length())));
                                return output;
                            }
                        } catch (Exception e) {
                            logger.error("解析data字段JSON失败: ", e);
                        }
                    } 
                    // 如果data字段是Map类型（直接的对象）
                    else if (dataField instanceof Map) {
                        Map<String, Object> dataObject = (Map<String, Object>) dataField;
                        if (dataObject != null && dataObject.containsKey("output")) {
                            return (String) dataObject.get("output");
                        }
                    }
                }
                
                // 兼容性：检查直接的output字段（旧格式支持）
                if (responseBody.containsKey("output")) {
                    return (String) responseBody.get("output");
                }
                
                logger.error("响应中未找到output字段，响应结构: {}", responseBody);
                return null;
            } else {
                logger.error("扣子工作流调用失败，状态码: {}", response.getStatusCode());
                return null;
            }
            
        } catch (Exception e) {
            // 网络或API调用异常处理
            logger.error("调用扣子工作流失败: ", e);
            return null;
        }
    }

    /**
     * 解析面试题目文本，提取结构化的题目数据
     * 
     * 智能解析算法：
     * 1. 新格式解析：数字. **题目类型**\n"题目内容"
     * 2. 宽松格式解析：兼容不标准的markdown格式
     * 3. 分行解析：兜底方案，按行分割处理
     * 4. 容错处理：解析失败时生成包含原文的备用题目
     * 
     * 数据清理：
     * - 移除markdown标记符号（**、*等）
     * - 清理多余的空白字符和换行符
     * - 标准化题目编号和分类
     * 
     * @param questionsText AI生成的原始题目文本
     * @return List<Map<String, Object>> 结构化的题目数据列表
     */
    private List<Map<String, Object>> parseQuestions(String questionsText) {
        List<Map<String, Object>> questions = new ArrayList<>();
        
        try {
            logger.info("开始解析面试题目文本，长度: {}", questionsText.length());
            
            // ========== 算法1：新格式精确匹配 ==========
            // 匹配格式：数字. **题目类型**\n"题目内容"
            Pattern newPattern = Pattern.compile(
                "(\\d+)\\s*\\.\\s*\\*\\*([^*]+)\\*\\*\\s*\\n\\s*\"([^\"]+)\"",
                Pattern.MULTILINE | Pattern.DOTALL
            );
            Matcher newMatcher = newPattern.matcher(questionsText);
            
            int questionId = 1;
            while (newMatcher.find()) {
                Map<String, Object> question = new HashMap<>();
                
                String number = newMatcher.group(1);
                String title = newMatcher.group(2).trim();
                String content = newMatcher.group(3).trim();
                
                // 清理标题和内容中的markdown标记
                title = title.replaceAll("\\*+", "").trim();
                content = content.replaceAll("\\*+", "").replaceAll("\\n", " ").trim();
                
                question.put("id", questionId++);
                question.put("number", number);
                question.put("title", title);
                question.put("content", content);
                question.put("category", title);
                question.put("isImportant", false);
                question.put("difficulty", "medium");
                
                questions.add(question);
                logger.debug("解析到题目 {}: {}", questionId, title);
            }
            
            // ========== 算法2：宽松格式匹配 ==========
            // 如果精确匹配失败，尝试更宽松的匹配规则
            if (questions.isEmpty()) {
                logger.info("新格式匹配失败，尝试宽松匹配...");
                
                // 匹配包含引号的题目内容
                Pattern loosePattern = Pattern.compile(
                    "(\\d+)\\s*\\.\\s*(.+?)\\s*\"([^\"]+)\"",
                    Pattern.MULTILINE | Pattern.DOTALL
                );
                Matcher looseMatcher = loosePattern.matcher(questionsText);
                
                questionId = 1;
                while (looseMatcher.find()) {
                    Map<String, Object> question = new HashMap<>();
                    
                    String number = looseMatcher.group(1);
                    String titlePart = looseMatcher.group(2).trim();
                    String content = looseMatcher.group(3).trim();
                    
                    // 从标题部分提取实际标题
                    String title = extractTitle(titlePart);
                    
                    // 清理内容
                    content = content.replaceAll("\\*+", "").replaceAll("\\n", " ").trim();
                    
                    question.put("id", questionId++);
                    question.put("number", number);
                    question.put("title", title);
                    question.put("content", content);
                    question.put("category", title);
                    question.put("isImportant", false);
                    question.put("difficulty", "medium");
                    
                    questions.add(question);
                    logger.debug("宽松匹配到题目 {}: {}", questionId, title);
                }
            }
            
            // ========== 算法3：分行解析（兜底方案） ==========
            if (questions.isEmpty()) {
                logger.info("所有正则匹配失败，使用分行处理...");
                parseQuestionsByLines(questionsText, questions);
            }
            
            logger.info("最终解析结果：共 {} 道题目", questions.size());
            
        } catch (Exception e) {
            logger.error("解析面试题目失败: ", e);
            
            // ========== 容错处理：创建备用题目 ==========
            // 解析失败时，将原始文本作为单个题目返回
            Map<String, Object> fallbackQuestion = new HashMap<>();
            fallbackQuestion.put("id", 1);
            fallbackQuestion.put("title", "AI生成的面试题目");
            fallbackQuestion.put("content", questionsText.replaceAll("\\*+", ""));
            fallbackQuestion.put("category", "综合");
            fallbackQuestion.put("isImportant", false);
            fallbackQuestion.put("difficulty", "medium");
            questions.add(fallbackQuestion);
        }
        
        return questions;
    }
    
    /**
     * 从标题部分提取实际标题
     * 
     * 标题清理规则：
     * 1. 移除所有markdown标记（*号）
     * 2. 处理中英文冒号分隔符
     * 3. 移除序号前缀（一、二、三等）
     * 4. 清理空白字符
     * 
     * @param titlePart 原始标题部分
     * @return String 清理后的标题
     */
    private String extractTitle(String titlePart) {
        // 移除markdown标记
        String title = titlePart.replaceAll("\\*+", "").trim();
        
        // 如果包含中文冒号或英文冒号，取冒号前的部分
        if (title.contains("：")) {
            title = title.split("：")[0].trim();
        } else if (title.contains(":")) {
            title = title.split(":")[0].trim();
        }
        
        // 移除可能的序号前缀
        title = title.replaceAll("^[一二三四五六七八九十]+、", "").trim();
        
        return title.isEmpty() ? "面试题目" : title;
    }
    
    /**
     * 按行解析题目（兜底方案）
     * 
     * 解析逻辑：
     * 1. 按换行符分割文本
     * 2. 识别数字开头的行作为题目标题
     * 3. 收集后续行作为题目内容
     * 4. 跳过空行和分隔符
     * 
     * 适用场景：
     * - AI生成的文本格式不规范
     * - 包含多种混合格式
     * - 其他解析算法失败时的兜底方案
     * 
     * @param questionsText 原始题目文本
     * @param questions 题目列表（引用传递，直接修改）
     */
    private void parseQuestionsByLines(String questionsText, List<Map<String, Object>> questions) {
        String[] lines = questionsText.split("\n");
        int questionId = 1;
        StringBuilder currentContent = new StringBuilder();
        String currentTitle = null;
        
        for (String line : lines) {
            line = line.trim();
            
            // 跳过空行和分隔符
            if (line.isEmpty() || line.matches("^-+$") || line.matches("^=+$")) {
                continue;
            }
            
            // 匹配数字开头的行（可能是题目）
            if (line.matches("^\\d+\\s*\\..*")) {
                // 保存上一个题目
                if (currentTitle != null && currentContent.length() > 0) {
                    addParsedQuestion(questions, questionId++, currentTitle, currentContent.toString());
                    currentContent = new StringBuilder();
                }
                
                // 提取新题目标题
                currentTitle = line.replaceAll("^\\d+\\s*\\.", "").replaceAll("\\*+", "").trim();
                if (currentTitle.isEmpty()) {
                    currentTitle = "面试题目 " + questionId;
                }
            } else if (currentTitle != null) {
                // 累积题目内容
                if (currentContent.length() > 0) {
                    currentContent.append(" ");
                }
                currentContent.append(line.replaceAll("\\*+", ""));
            }
        }
        
        // 添加最后一个题目
        if (currentTitle != null && currentContent.length() > 0) {
            addParsedQuestion(questions, questionId, currentTitle, currentContent.toString());
        }
    }
    
    /**
     * 添加解析后的题目到题目列表
     * 
     * 功能说明：
     * - 将解析后的题目数据标准化并添加到题目列表
     * - 设置默认的题目属性（重要性、难度等）
     * - 记录题目添加日志
     * 
     * @param questions 题目列表（引用传递）
     * @param questionId 题目ID
     * @param title 题目标题
     * @param content 题目内容
     */
    private void addParsedQuestion(List<Map<String, Object>> questions, int questionId, String title, String content) {
        Map<String, Object> question = new HashMap<>();
        question.put("id", questionId);
        question.put("number", String.valueOf(questionId));
        question.put("title", title);
        question.put("content", content.trim());
        question.put("category", title);
        question.put("isImportant", false);
        question.put("difficulty", "medium");
        questions.add(question);
        
        logger.debug("添加题目 {}: {}", questionId, title);
    }
    
    /**
     * 保存用户面试回答
     * 
     * 核心功能：
     * 1. 接收用户对某个面试题目的回答
     * 2. 验证用户身份和请求参数
     * 3. 保存或更新答案到数据库
     * 4. 支持答案的多次修改和保存
     * 
     * 业务逻辑：
     * - 每个题目对应一个答案记录
     * - 支持草稿保存（未提交状态）
     * - 记录答题时长和时间戳
     * - 自动更新答案状态
     * 
     * 数据处理：
     * - 检查是否已存在答案记录
     * - 存在则更新，不存在则新建
     * - 自动设置答案状态为"已回答"
     * 
     * @param request 包含答案数据的请求体
     *                - sessionId: 面试会话ID（必填）
     *                - questionId: 题目ID（必填）
     *                - questionTitle: 题目标题
     *                - questionContent: 题目内容
     *                - questionCategory: 题目分类
     *                - answerContent: 回答内容（必填）
     *                - answerDuration: 答题时长（秒）
     * @param token JWT认证令牌，用于用户身份验证
     * @return ResponseEntity 保存结果状态信息
     */
    @PostMapping("/saveAnswer")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> saveAnswer(@RequestBody Map<String, Object> request,
                                                         @RequestHeader(value = "Authorization", required = false) String token) {
        logger.info("=== 开始保存面试回答 ===");
        Map<String, Object> response = new HashMap<>();
        
        try {
            // ========== 用户身份验证 ==========
            User user = getCurrentUser(token);
            if (user == null) {
                logger.warn("用户未登录，拒绝保存回答请求");
                response.put("success", false);
                response.put("message", "请先登录后再保存回答");
                return ResponseEntity.status(401).body(response);
            }
            
            // ========== 提取请求参数 ==========
            String sessionId = (String) request.get("sessionId");
            Integer questionId = (Integer) request.get("questionId");
            String questionTitle = (String) request.get("questionTitle");
            String questionContent = (String) request.get("questionContent");
            String questionCategory = (String) request.get("questionCategory");
            String answerContent = (String) request.get("answerContent");
            Integer answerDuration = (Integer) request.get("answerDuration");
            
            logger.info("保存回答请求 - 用户ID: {}, 会话ID: {}, 题目ID: {}, 回答长度: {}", 
                       user.getId(), sessionId, questionId, 
                       answerContent != null ? answerContent.length() : 0);
            
            // ========== 参数验证 ==========
            // 验证会话ID
            if (sessionId == null || sessionId.trim().isEmpty()) {
                response.put("success", false);
                response.put("message", "会话ID不能为空");
                return ResponseEntity.badRequest().body(response);
            }
            
            // 验证题目ID
            if (questionId == null) {
                response.put("success", false);
                response.put("message", "题目ID不能为空");
                return ResponseEntity.badRequest().body(response);
            }
            
            // 验证回答内容
            if (answerContent == null || answerContent.trim().isEmpty()) {
                response.put("success", false);
                response.put("message", "回答内容不能为空");
                return ResponseEntity.badRequest().body(response);
            }
            
            // 检查是否已存在回答记录（包括未回答的）
            InterviewAnswer existingAnswer = getExistingAnswerIncludingEmpty(user.getId(), sessionId, questionId);
            
            if (existingAnswer != null) {
                // 更新已有回答记录
                existingAnswer.setAnswerContent(answerContent.trim());
                existingAnswer.setAnswerDuration(answerDuration);
                existingAnswer.setStatus(1); // 设置为已回答
                existingAnswer.setUpdateTime(LocalDateTime.now());
                
                int updated = interviewAnswerMapper.updateAnswer(existingAnswer);
                if (updated > 0) {
                    response.put("success", true);
                    response.put("message", "回答保存成功");
                    response.put("answerId", existingAnswer.getId());
                } else {
                    response.put("success", false);
                    response.put("message", "回答保存失败");
                }
            } else {
                // 创建新回答（兼容旧数据）
                InterviewAnswer answer = new InterviewAnswer(
                    user.getId(),
                    sessionId,
                    questionId,
                    questionTitle,
                    questionContent,
                    questionCategory,
                    answerContent.trim()
                );
                answer.setAnswerDuration(answerDuration);
                answer.setStatus(1); // 已回答
                
                int inserted = interviewAnswerMapper.insertAnswer(answer);
                if (inserted > 0) {
                    response.put("success", true);
                    response.put("message", "回答保存成功");
                    response.put("answerId", answer.getId());
                } else {
                    response.put("success", false);
                    response.put("message", "回答保存失败");
                }
            }
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            logger.error("保存面试回答失败: ", e);
            e.printStackTrace();
            
            response.put("success", false);
            response.put("message", "服务器内部错误: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }
    
    /**
     * 批量提交面试答案
     */
    
    /**
     * 批量提交所有面试答案
     * 
     * 核心功能：
     * 1. 接收用户完成面试后的所有答案
     * 2. 批量保存或更新所有答案到数据库
     * 3. 更新面试会话状态为已完成
     * 4. 计算统计信息（已回答数、完成度等）
     * 
     * 业务逻辑：
     * - 支持部分答案提交（允许空答案）
     * - 自动更新会话的完成状态
     * - 生成模拟评分（后续可接入AI分析）
     * - 记录答题时长和时间戳
     * 
     * 数据处理：
     * - 逐个答案进行保存，确保数据一致性
     * - 检查并更新现有答案记录
     * - 统计有效答案数量
     * - 设置答案状态（已回答/未回答）
     * 
     * @param request 包含所有答案的请求体
     *                - sessionId: 面试会话ID（必填）
     *                - answers: 答案列表（必填）
     *                - targetPosition: 目标职位
     *                - workExperience: 工作经验
     *                - skills: 技能描述
     * @param token JWT认证令牌，用于用户身份验证
     * @return ResponseEntity 批量提交结果和统计信息
     */
    @PostMapping("/submitAll")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> submitAllAnswers(@RequestBody Map<String, Object> request,
                                                              @RequestHeader(value = "Authorization", required = false) String token) {
        logger.info("=== 开始批量提交面试答案 ===");
        Map<String, Object> response = new HashMap<>();
        
        try {
            // ========== 用户身份验证 ==========
            User user = getCurrentUser(token);
            if (user == null) {
                logger.warn("用户未登录，拒绝批量提交请求");
                response.put("success", false);
                response.put("message", "请先登录后再提交答案");
                return ResponseEntity.status(401).body(response);
            }
            
            // 获取请求参数
            String sessionId = (String) request.get("sessionId");
            @SuppressWarnings("unchecked")
            List<Map<String, Object>> answers = (List<Map<String, Object>>) request.get("answers");
            String targetPosition = (String) request.get("targetPosition");
            String workExperience = (String) request.get("workExperience");
            String skills = (String) request.get("skills");
            
            // 参数验证
            if (sessionId == null || sessionId.trim().isEmpty()) {
                response.put("success", false);
                response.put("message", "会话ID不能为空");
                return ResponseEntity.badRequest().body(response);
            }
            
            if (answers == null || answers.isEmpty()) {
                response.put("success", false);
                response.put("message", "答案列表不能为空");
                return ResponseEntity.badRequest().body(response);
            }
            
            // 获取面试会话记录（应该在生成题目时已创建）
            InterviewSession session = interviewSessionMapper.findBySessionId(sessionId);
            if (session == null) {
                response.put("success", false);
                response.put("message", "面试会话不存在，请重新生成题目");
                return ResponseEntity.badRequest().body(response);
            }
            
            // 确保题目总数正确
            if (session.getTotalQuestions() == null || session.getTotalQuestions() != answers.size()) {
                interviewSessionMapper.updateTotalQuestions(sessionId, answers.size());
                logger.info("更新面试会话题目数: {} -> {}", sessionId, answers.size());
            }
            
            int savedCount = 0;
            int totalCount = answers.size();
            
            // 逐个保存答案
            for (Map<String, Object> answerData : answers) {
                try {
                    Integer questionId = (Integer) answerData.get("questionId");
                    String questionTitle = (String) answerData.get("questionTitle");
                    String questionContent = (String) answerData.get("questionContent");
                    String questionCategory = (String) answerData.get("questionCategory");
                    String answerContent = (String) answerData.get("answerContent");
                    Integer answerDuration = (Integer) answerData.get("answerDuration");
                    
                    // 基础验证
                    if (questionId == null || answerContent == null) {
                        continue;
                    }
                    
                    // 检查是否为空答案
                    boolean hasAnswer = !answerContent.trim().isEmpty();
                    
                    // 检查是否已存在回答记录（包括未回答的）
                    InterviewAnswer existingAnswer = getExistingAnswerIncludingEmpty(user.getId(), sessionId, questionId);
                    
                    if (existingAnswer != null) {
                        // 更新已有回答记录
                        existingAnswer.setAnswerContent(answerContent.trim());
                        existingAnswer.setAnswerDuration(answerDuration);
                        existingAnswer.setStatus(hasAnswer ? 1 : 0); // 有答案设置为已回答，无答案保持未回答
                        existingAnswer.setUpdateTime(LocalDateTime.now());
                        
                        if (interviewAnswerMapper.updateAnswer(existingAnswer) > 0) {
                            if (hasAnswer) savedCount++; // 只有有答案的才计入已回答数
                        }
                    } else {
                        // 创建新回答（兼容旧数据）
                        InterviewAnswer answer = new InterviewAnswer(
                            user.getId(),
                            sessionId,
                            questionId,
                            questionTitle,
                            questionContent,
                            questionCategory,
                            answerContent.trim()
                        );
                        answer.setAnswerDuration(answerDuration);
                        answer.setStatus(hasAnswer ? 1 : 0); // 有答案设置为已回答，无答案设置为未回答
                        
                        if (interviewAnswerMapper.insertAnswer(answer) > 0) {
                            if (hasAnswer) savedCount++; // 只有有答案的才计入已回答数
                        }
                    }
                } catch (Exception e) {
                    logger.error("保存单个答案失败: ", e);
                    // 继续处理其他答案
                }
            }
            
            // 更新会话状态为已完成，并更新已回答题目数
            if (session != null) {
                interviewSessionMapper.updateAnsweredQuestions(sessionId, savedCount);
                
                // 如果所有题目都已回答，则标记为已完成
                if (savedCount > 0) {
                    // 计算简单的模拟分数（后续可以用AI分析替换）
                    BigDecimal totalScore = new BigDecimal("85.0");
                    BigDecimal positionMatchRate = new BigDecimal("82.0");
                    String comprehensiveRating = "B+";
                    
                    // 标记会话为已完成
                    interviewSessionMapper.completeSession(sessionId, LocalDateTime.now(), totalScore, positionMatchRate, comprehensiveRating);
                    logger.info("面试会话已完成: {}", sessionId);
                }
            }
            
            response.put("success", true);
            response.put("message", "批量提交完成");
            response.put("totalCount", totalCount);
            response.put("savedCount", savedCount);
            response.put("sessionId", sessionId);
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            logger.error("批量提交面试答案失败: ", e);
            e.printStackTrace();
            
            response.put("success", false);
            response.put("message", "服务器内部错误: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }
    
    /**
     * 获取用户面试回答历史
     * 
     * 查询功能：
     * 1. 根据会话ID查询特定面试的所有回答
     * 2. 查询用户的所有历史回答记录
     * 3. 支持分页查询，避免数据量过大
     * 
     * 应用场景：
     * - 面试答题页面加载已保存的答案
     * - 用户查看历史面试记录
     * - 分析页面获取答案数据
     * 
     * 数据安全：
     * - 严格的用户身份验证
     * - 只能查询自己的答案记录
     * - 防止越权访问其他用户数据
     * 
     * @param sessionId 会话ID（可选），指定则查询特定会话的答案，否则查询所有历史答案
     * @param token JWT认证令牌，用于用户身份验证
     * @return ResponseEntity 包含答案列表和统计信息
     */
    @GetMapping("/answers")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> getUserAnswers(@RequestParam(required = false) String sessionId,
                                                            @RequestHeader(value = "Authorization", required = false) String token) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 获取用户信息
            User user = getCurrentUser(token);
            if (user == null) {
                response.put("success", false);
                response.put("message", "请先登录");
                return ResponseEntity.status(401).body(response);
            }
            
            List<InterviewAnswer> answers;
            if (sessionId != null && !sessionId.trim().isEmpty()) {
                // 获取指定会话的回答
                answers = interviewAnswerMapper.selectAnswersByUserAndSession(user.getId(), sessionId);
            } else {
                // 获取用户所有回答历史（分页）
                answers = interviewAnswerMapper.selectAnswersByUserId(user.getId(), 0, 50);
            }
            
            response.put("success", true);
            response.put("answers", answers);
            response.put("total", answers.size());
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            logger.error("获取面试回答失败: ", e);
            e.printStackTrace();
            
            response.put("success", false);
            response.put("message", "服务器内部错误: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }
    
    /**
     * 从JWT token获取当前用户信息
     * 
     * 认证流程：
     * 1. 验证Token格式（Bearer前缀）
     * 2. 提取JWT令牌内容
     * 3. 解析用户名信息
     * 4. 验证Token有效性
     * 5. 查询用户详细信息
     * 
     * 安全机制：
     * - 严格的Token格式验证
     * - JWT签名验证
     * - Token过期时间检查
     * - 异常安全处理
     * 
     * @param token JWT认证令牌，格式为 "Bearer xxxxx"
     * @return User 用户对象，认证失败时返回null
     */
    private User getCurrentUser(String token) {
        // 验证Token格式
        if (token == null || !token.startsWith("Bearer ")) {
            return null;
        }
        
        try {
            // 提取JWT内容（去除Bearer前缀）
            String jwt = token.substring(7);
            
            // 解析用户名
            String username = jwtUtil.getUsernameFromToken(jwt);
            
            // 验证Token有效性并查询用户信息
            if (username != null && jwtUtil.validateToken(jwt, username)) {
                return userMapper.findByUsername(username);
            }
        } catch (Exception e) {
            // JWT解析异常处理
            logger.error("解析用户token失败: ", e);
        }
        
        return null;
    }
    
    /**
     * 获取用户在指定会话中对特定题目的已有回答
     * 
     * 查询逻辑：
     * - 仅查询有回答内容的记录
     * - 用于检查答案是否已存在
     * - 支持答案更新判断
     * 
     * @param userId 用户ID
     * @param sessionId 面试会话ID
     * @param questionId 题目ID
     * @return InterviewAnswer 已有回答，不存在时返回null
     */
    private InterviewAnswer getExistingAnswer(Long userId, String sessionId, Integer questionId) {
        List<InterviewAnswer> answers = interviewAnswerMapper.selectAnswersByUserAndSession(userId, sessionId);
        return answers.stream()
            .filter(answer -> answer.getQuestionId().equals(questionId))
            .findFirst()
            .orElse(null);
    }
    
    /**
     * 获取用户在指定会话中对特定题目的回答记录（包括空答案）
     * 
     * 查询逻辑：
     * - 查询所有答案记录，包括未回答的空记录
     * - 用于批量提交时的答案更新
     * - 确保每个题目都有对应的答案记录
     * 
     * @param userId 用户ID
     * @param sessionId 面试会话ID
     * @param questionId 题目ID
     * @return InterviewAnswer 答案记录，不存在时返回null
     */
    private InterviewAnswer getExistingAnswerIncludingEmpty(Long userId, String sessionId, Integer questionId) {
        List<InterviewAnswer> answers = interviewAnswerMapper.selectAllAnswersByUserAndSession(userId, sessionId);
        return answers.stream()
            .filter(answer -> answer.getQuestionId().equals(questionId))
            .findFirst()
            .orElse(null);
    }
    
    /**
     * 面试结果分析页面（旧版本，已弃用）
     * 
     * 功能说明：
     * - 显示面试分析结果页面
     * - 包含用户权限验证和会话归属检查
     * - 已被新版分析页面替代
     * 
     * 安全验证：
     * - JWT用户身份认证
     * - 会话归属权限检查
     * - 未授权访问重定向处理
     * 
     * @param sessionId 面试会话ID
     * @param token JWT认证令牌
     * @return String 页面模板名称或重定向路径
     */
    @GetMapping("/analysis-old")
    public String analysisPage(@RequestParam String sessionId, 
                              @RequestHeader(value = "Authorization", required = false) String token) {
        // 验证用户权限
        User user = getCurrentUser(token);
        if (user == null) {
            return "redirect:/login";
        }
        
        // 验证会话归属
        boolean userOwnsSession = interviewSessionMapper.userOwnsSession(user.getId(), sessionId);
        if (!userOwnsSession) {
            return "redirect:/mianshiwenti";
        }
        
        return "interview-analysis";
    }
    
    /**
     * 面试记录查看页面
     * 
     * 功能说明：
     * - 返回面试记录列表页面
     * - 前端JavaScript负责用户认证和数据加载
     * - 支持历史面试记录的查看和管理
     * 
     * @return String 面试记录页面模板名称
     */
    @GetMapping("/records")
    public String recordsPage() {
        // 直接返回页面，让前端JavaScript处理认证
        return "interview-records";
    }
    
    /**
     * 获取用户面试记录列表API
     * 
     * 核心功能：
     * 1. 查询用户的所有面试会话记录
     * 2. 获取每个会话的题目和答案统计
     * 3. 计算答题完成度和进度信息
     * 4. 返回详细的历史记录数据
     * 
     * 查询逻辑：
     * - 仅查询包含题目的面试会话
     * - 统计已回答和未回答的题目数量
     * - 计算答题完成度百分比
     * - 包含答案内容的详细信息
     * 
     * 数据统计：
     * - 总题目数量统计
     * - 已回答题目数量统计
     * - 答题状态分析（status字段和内容检查）
     * - 会话完成情况评估
     * 
     * @param token JWT认证令牌，用于用户身份验证
     * @return ResponseEntity 包含面试记录列表和统计信息
     */
    @GetMapping("/records/list")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> getRecordsList(@RequestHeader(value = "Authorization", required = false) String token) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 验证用户
            User user = getCurrentUser(token);
            if (user == null) {
                logger.warn("用户认证失败，token: {}", token != null ? token.substring(0, Math.min(20, token.length())) + "..." : "null");
                response.put("success", false);
                response.put("message", "请先登录");
                return ResponseEntity.status(401).body(response);
            }
            
            logger.info("当前用户: ID={}, username={}", user.getId(), user.getUsername());
            
            // 直接获取有题目记录的面试会话
            List<InterviewSession> allSessions = interviewSessionMapper.findSessionsWithAnswersByUserId(user.getId());
            logger.info("用户ID: {}, 查询到有题目的面试记录数量: {}", user.getId(), allSessions.size());
            
            // 为每个会话获取对应的答案
            List<Map<String, Object>> recordsWithAnswers = new ArrayList<>();
            
            for (InterviewSession session : allSessions) {
                // 获取该会话的所有题目（包括未回答的）
                List<InterviewAnswer> allAnswers = interviewAnswerMapper.selectAllAnswersByUserAndSession(user.getId(), session.getSessionId());
                logger.info("会话ID: {}, 题目总数: {}", session.getSessionId(), allAnswers.size());
                
                // 只要有题目就添加到记录中（不管是否回答）
                if (allAnswers != null && !allAnswers.isEmpty()) {
                    // 详细调试每个答案的状态
                    logger.info("=== 答案详情调试 ===");
                    for (InterviewAnswer answer : allAnswers) {
                        boolean hasContent = answer.getAnswerContent() != null && !answer.getAnswerContent().trim().isEmpty();
                        logger.info("题目{}: status={}, 有内容={}, 内容长度={}", answer.getQuestionId(), answer.getStatus(), hasContent, answer.getAnswerContent() != null ? answer.getAnswerContent().length() : 0);
                    }
                    logger.info("=== 答案详情调试结束 ===");
                    
                    // 统计已回答的题目数（既要status=1，也要有内容）
                    long answeredCount = allAnswers.stream().filter(answer -> 
                        answer.getStatus() == 1 && 
                        answer.getAnswerContent() != null && 
                        !answer.getAnswerContent().trim().isEmpty()
                    ).count();
                    
                    // 也统计有内容但status不是1的情况
                    long hasContentCount = allAnswers.stream().filter(answer -> 
                        answer.getAnswerContent() != null && 
                        !answer.getAnswerContent().trim().isEmpty()
                    ).count();
                    
                    logger.info("统计结果: status=1的={}, 有内容的={}, 最终已回答={}", allAnswers.stream().filter(answer -> answer.getStatus() == 1).count(), hasContentCount, answeredCount);
                    
                    Map<String, Object> recordData = new HashMap<>();
                    recordData.put("session", session);
                    recordData.put("answers", allAnswers);
                    recordData.put("answerCount", allAnswers.size());
                    recordData.put("answeredCount", Math.max(answeredCount, hasContentCount)); // 使用有内容的数量
                    
                    recordsWithAnswers.add(recordData);
                    logger.info("添加会话记录: {}, 题目数: {}, 已回答: {}", session.getSessionId(), allAnswers.size(), Math.max(answeredCount, hasContentCount));
                }
            }
            
            logger.info("最终返回的有答案的面试记录数量: {}", recordsWithAnswers.size());
            
            response.put("success", true);
            response.put("records", recordsWithAnswers);
            response.put("totalCount", allSessions.size());
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            logger.error("获取面试记录失败: ", e);
            e.printStackTrace();
            
            response.put("success", false);
            response.put("message", "服务器内部错误: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }
    
    /**
     * 删除面试记录API
     * 
     * 核心功能：
     * 1. 删除指定会话的所有相关数据
     * 2. 验证用户权限和会话归属
     * 3. 确保数据安全删除
     * 4. 清理关联的答案记录
     * 
     * 安全机制：
     * - 严格的用户身份验证
     * - 会话归属权限检查
     * - 防止越权删除操作
     * - 事务安全保证
     * 
     * 数据清理：
     * - 删除面试会话记录
     * - 删除关联的所有答案
     * - 清理相关统计数据
     * - 确保数据一致性
     * 
     * @param sessionId 要删除的面试会话ID
     * @param token JWT认证令牌，用于用户身份验证
     * @return ResponseEntity 删除操作结果状态
     */
    @DeleteMapping("/records/{sessionId}")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> deleteRecord(@PathVariable String sessionId,
                                                           @RequestHeader(value = "Authorization", required = false) String token) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 验证用户
            User user = getCurrentUser(token);
            if (user == null) {
                response.put("success", false);
                response.put("message", "请先登录");
                return ResponseEntity.status(401).body(response);
            }
            
            // 验证会话归属
            boolean userOwnsSession = interviewSessionMapper.userOwnsSession(user.getId(), sessionId);
            if (!userOwnsSession) {
                response.put("success", false);
                response.put("message", "无权删除此面试记录");
                return ResponseEntity.status(403).body(response);
            }
            
            // 执行软删除
            int deleted = interviewSessionMapper.deleteSession(sessionId);
            if (deleted > 0) {
                response.put("success", true);
                response.put("message", "面试记录删除成功");
            } else {
                response.put("success", false);
                response.put("message", "删除失败，记录不存在");
            }
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            logger.error("删除面试记录失败: ", e);
            e.printStackTrace();
            
            response.put("success", false);
            response.put("message", "服务器内部错误: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }

    /**
     * 获取面试分析数据API
     */
    @GetMapping("/analysis/data")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> getAnalysisData(@RequestParam String sessionId,
                                                             @RequestHeader(value = "Authorization", required = false) String token) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 验证用户
            User user = getCurrentUser(token);
            if (user == null) {
                response.put("success", false);
                response.put("message", "请先登录");
                return ResponseEntity.status(401).body(response);
            }
            
            // 验证会话归属
            boolean userOwnsSession = interviewSessionMapper.userOwnsSession(user.getId(), sessionId);
            if (!userOwnsSession) {
                response.put("success", false);
                response.put("message", "无权访问此面试记录");
                return ResponseEntity.status(403).body(response);
            }
            
            // 获取会话信息
            InterviewSession session = interviewSessionMapper.findBySessionId(sessionId);
            if (session == null) {
                response.put("success", false);
                response.put("message", "面试记录不存在");
                return ResponseEntity.status(404).body(response);
            }
            
            // 获取答案列表（包括未回答的题目）
            List<InterviewAnswer> answers = interviewAnswerMapper.selectAllAnswersByUserAndSession(user.getId(), sessionId);
            
            // TODO: 实现AI分析逻辑，计算各项得分
            // 暂时返回模拟数据
            response.put("success", true);
            response.put("session", session);
            response.put("answers", answers);
            response.put("analysis", generateMockAnalysis(session, answers));
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            logger.error("获取面试分析数据失败: ", e);
            e.printStackTrace();
            
            response.put("success", false);
            response.put("message", "服务器内部错误");
            return ResponseEntity.internalServerError().body(response);
        }
    }
    
    /**
     * 生成模拟分析数据（临时方法，后续会替换为真实AI分析）
     * 
     * 模拟功能：
     * 1. 生成随机但合理的评分数据
     * 2. 模拟各项能力维度评估
     * 3. 生成优势分析和改进建议
     * 4. 计算综合评级等级
     * 
     * 评分维度：
     * - 技术能力评分（technicalScore）
     * - 表达能力评分（expressionScore）
     * - 逻辑思维评分（logicScore）
     * - 经验匹配评分（experienceScore）
     * 
     * 输出结果：
     * - 总分和等级评定
     * - 岗位匹配度分析
     * - 具体优势点列举
     * - 改进建议分类
     * 
     * @param session 面试会话信息
     * @param answers 用户回答列表
     * @return Map<String, Object> 模拟分析结果数据
     */
    private Map<String, Object> generateMockAnalysis(InterviewSession session, List<InterviewAnswer> answers) {
        Map<String, Object> analysis = new HashMap<>();
        
        // 模拟总分计算
        int totalScore = 75 + (int)(Math.random() * 20); // 75-95分随机
        analysis.put("totalScore", totalScore);
        
        // 模拟岗位匹配度
        int matchRate = 80 + (int)(Math.random() * 15); // 80-95%随机
        analysis.put("positionMatchRate", matchRate);
        
        // 模拟综合评级
        String rating = totalScore >= 90 ? "A+" : totalScore >= 85 ? "A" : totalScore >= 80 ? "B+" : totalScore >= 75 ? "B" : "C+";
        analysis.put("comprehensiveRating", rating);
        
        // 模拟各项能力得分
        analysis.put("technicalScore", 85);
        analysis.put("expressionScore", 78);
        analysis.put("logicScore", 82);
        analysis.put("experienceScore", 88);
        
        // 模拟优势分析
        List<String> strengths = new ArrayList<>();
        strengths.add("准确列举了6个核心生命周期方法");
        strengths.add("正确区分了class组件与函数组件的差异");
        analysis.put("strengths", strengths);
        
        // 模拟改进建议
        Map<String, List<String>> improvements = new HashMap<>();
        improvements.put("技术表达", List.of("建议补充Hooks的使用经验", "增加TypeScript类型定义示例"));
        improvements.put("表达能力", List.of("使用STAR法则阐述项目经验", "控制语速（当前平均语速偏快）"));
        analysis.put("improvements", improvements);
        
        // 模拟结果有效期
        analysis.put("expiryDays", 30);
        
        return analysis;
    }

    /**
     * 调试API - 检查用户的面试数据
     * 
     * 调试功能：
     * 1. 查看用户的所有面试会话
     * 2. 检查每个会话的答案数据
     * 3. 验证数据完整性和一致性
     * 4. 协助排查数据相关问题
     * 
     * 数据统计：
     * - 用户基本信息
     * - 面试会话总数
     * - 每个会话的答案统计
     * - 数据结构完整性检查
     * 
     * 使用场景：
     * - 开发调试和问题排查
     * - 数据结构验证
     * - 用户反馈问题定位
     * 
     * @param token JWT认证令牌，用于用户身份验证
     * @return ResponseEntity 包含用户完整数据的调试信息
     */
    @GetMapping("/debug/userdata")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> debugUserData(@RequestHeader(value = "Authorization", required = false) String token) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 验证用户
            User user = getCurrentUser(token);
            if (user == null) {
                response.put("success", false);
                response.put("message", "请先登录");
                return ResponseEntity.status(401).body(response);
            }
            
            // 获取用户信息
            response.put("user", Map.of(
                "id", user.getId(),
                "username", user.getUsername()
            ));
            
            // 获取所有面试会话
            List<InterviewSession> allSessions = interviewSessionMapper.findByUserId(user.getId());
            response.put("totalSessions", allSessions.size());
            response.put("sessions", allSessions);
            
            // 获取所有面试答案
            List<Map<String, Object>> sessionAnswers = new ArrayList<>();
            for (InterviewSession session : allSessions) {
                List<InterviewAnswer> answers = interviewAnswerMapper.selectAnswersByUserAndSession(user.getId(), session.getSessionId());
                sessionAnswers.add(Map.of(
                    "sessionId", session.getSessionId(),
                    "answerCount", answers.size(),
                    "answers", answers
                ));
            }
            response.put("sessionAnswers", sessionAnswers);
            
            response.put("success", true);
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            logger.error("调试用户数据失败: ", e);
            e.printStackTrace();
            
            response.put("success", false);
            response.put("message", "服务器内部错误: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }
    
    /**
     * 面试评估API - AI智能评估面试结果
     * 
     * 核心功能：
     * 1. 调用AI评估服务分析用户回答
     * 2. 生成详细的能力评估报告
     * 3. 计算各项能力维度得分
     * 4. 提供个性化改进建议
     * 
     * 评估维度：
     * - 技术能力和专业知识
     * - 表达能力和沟通技巧
     * - 逻辑思维和问题解决
     * - 工作经验和岗位匹配
     * 
     * AI分析内容：
     * - 回答质量和深度分析
     * - 关键词匹配度评估
     * - 表达逻辑性判断
     * - 专业术语使用准确性
     * 
     * @param request 评估请求体，包含sessionId
     * @param token JWT认证令牌，用于用户身份验证
     * @return ResponseEntity 包含AI评估结果和分析报告
     */
    @PostMapping("/evaluate")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> evaluateInterview(@RequestBody Map<String, Object> request,
                                                               @RequestHeader(value = "Authorization", required = false) String token) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 获取用户信息
            User user = getCurrentUser(token);
            if (user == null) {
                response.put("success", false);
                response.put("message", "请先登录");
                return ResponseEntity.status(401).body(response);
            }
            
            // 获取会话ID
            String sessionId = (String) request.get("sessionId");
            if (sessionId == null || sessionId.trim().isEmpty()) {
                response.put("success", false);
                response.put("message", "会话ID不能为空");
                return ResponseEntity.badRequest().body(response);
            }
            
            // 调用评估服务
            Map<String, Object> evaluationResult = interviewEvaluationService.evaluateInterview(user.getId(), sessionId);
            
            response.put("success", true);
            response.put("message", "面试评估完成");
            response.put("data", evaluationResult);
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            logger.error("面试评估失败: ", e);
            e.printStackTrace();
            
            response.put("success", false);
            response.put("message", "评估失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }
    
    /**
     * 获取面试分析结果API
     * 
     * 查询功能：
     * 1. 获取指定会话的AI分析结果
     * 2. 返回详细的评估报告数据
     * 3. 包含各项能力得分和建议
     * 4. 支持分析结果的重复查看
     * 
     * 返回数据：
     * - 总分和综合评级
     * - 各维度能力得分
     * - 优势分析和改进建议
     * - 岗位匹配度评估
     * 
     * 安全控制：
     * - 用户身份验证
     * - 数据权限检查
     * - 分析结果缓存机制
     * 
     * @param sessionId 面试会话ID
     * @param token JWT认证令牌，用于用户身份验证
     * @return ResponseEntity 包含完整的分析结果数据
     */
    @GetMapping("/analysis/{sessionId}")
    @ResponseBody
    public ResponseEntity<Map<String, Object>> getAnalysisResult(@PathVariable String sessionId,
                                                               @RequestHeader(value = "Authorization", required = false) String token) {
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 获取用户信息
            User user = getCurrentUser(token);
            if (user == null) {
                response.put("success", false);
                response.put("message", "请先登录");
                return ResponseEntity.status(401).body(response);
            }
            
            // 获取分析结果
            Map<String, Object> analysisData = interviewEvaluationService.getAnalysisResult(user.getId(), sessionId);
            
            response.put("success", true);
            response.put("data", analysisData);
            
            return ResponseEntity.ok(response);
            
        } catch (Exception e) {
            logger.error("获取分析结果失败: ", e);
            e.printStackTrace();
            
            response.put("success", false);
            response.put("message", "获取分析结果失败: " + e.getMessage());
            return ResponseEntity.internalServerError().body(response);
        }
    }
    
    /**
     * 面试分析结果页面
     * 
     * 页面功能：
     * 1. 显示AI面试分析结果页面
     * 2. 支持多种Token传递方式
     * 3. 用户权限验证和会话检查
     * 4. 分析结果可视化展示
     * 
     * Token处理：
     * - 优先使用URL参数中的token
     * - 备用Header中的Authorization token
     * - 灵活支持不同的调用方式
     * 
     * 安全验证：
     * - JWT用户身份认证
     * - 会话归属权限检查
     * - 未授权访问重定向
     * 
     * @param sessionId 面试会话ID
     * @param urlToken URL参数中的token（可选）
     * @param headerToken Header中的Authorization token（可选）
     * @return String 分析结果页面模板名称或重定向路径
     */
    @GetMapping("/analysis")
    public String analysisResultPage(@RequestParam String sessionId,
                                   @RequestParam(value = "token", required = false) String urlToken,
                                   @RequestHeader(value = "Authorization", required = false) String headerToken) {
        // 优先使用URL中的token，如果没有则使用header中的token
        String token = urlToken != null ? "Bearer " + urlToken : headerToken;
        
        // 验证用户权限
        User user = getCurrentUser(token);
        if (user == null) {
            return "redirect:/login";
        }
        
        // 验证会话归属
        boolean userOwnsSession = interviewSessionMapper.userOwnsSession(user.getId(), sessionId);
        if (!userOwnsSession) {
            return "redirect:/interview/records";
        }
        
        return "interview-analysis-result";
    }

    /**
     * 生成面试分析报告PDF
     * 
     * 功能说明：
     * 1. 获取指定会话的完整分析数据
     * 2. 调用PDF生成服务创建报告
     * 3. 返回PDF文件供用户下载
     * 4. 支持浏览器直接下载或预览
     * 
     * 文件处理：
     * - 设置正确的Content-Type为application/pdf
     * - 设置Content-Disposition为attachment触发下载
     * - 文件名包含会话ID和时间戳
     * 
     * 安全控制：
     * - 用户身份验证
     * - 数据权限检查
     * - 分析结果存在性验证
     * 
     * @param sessionId 面试会话ID
     * @param token JWT认证令牌，用于用户身份验证
     * @return ResponseEntity 包含PDF文件的字节流
     */
    @GetMapping("/analysis/{sessionId}/pdf")
    public ResponseEntity<byte[]> generatePdfReport(@PathVariable String sessionId,
                                                   @RequestHeader(value = "Authorization", required = false) String token) {
        try {
            // 获取用户信息
            User user = getCurrentUser(token);
            if (user == null) {
                return ResponseEntity.status(401).build();
            }
            
            logger.info("用户 {} 请求生成PDF报告: sessionId={}", user.getUsername(), sessionId);
            
            // 获取分析结果数据
            Map<String, Object> analysisData = interviewEvaluationService.getAnalysisResult(user.getId(), sessionId);
            
            InterviewSession session = (InterviewSession) analysisData.get("session");
            InterviewAnalysis analysis = (InterviewAnalysis) analysisData.get("analysis");
            List<InterviewAnswer> answers = (List<InterviewAnswer>) analysisData.get("answers");
            
            // 生成PDF
            byte[] pdfBytes = pdfReportService.generateInterviewReportPdf(session, analysis, answers);
            
            // 设置响应头（HTML格式）
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.TEXT_HTML);
            headers.setContentDisposition(ContentDisposition.builder("inline")
                .filename("interview_report_" + sessionId + "_" + 
                    java.time.LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")) + ".html")
                .build());
            headers.setContentLength(pdfBytes.length);
            
            logger.info("PDF报告生成成功: sessionId={}, 文件大小={}KB", sessionId, pdfBytes.length / 1024);
            
            return ResponseEntity.ok()
                .headers(headers)
                .body(pdfBytes);
                
        } catch (Exception e) {
            logger.error("生成PDF报告失败: sessionId={}", sessionId, e);
            return ResponseEntity.internalServerError().build();
        }
    }
} 